home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / timed / readmsg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-23  |  10.0 KB  |  448 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)readmsg.c    2.10 (Berkeley) 12/23/87";
  15. #endif /* not lint */
  16.  
  17. #include "globals.h"
  18. #include <protocols/timed.h>
  19.  
  20. extern char *tsptype[];
  21.  
  22. /*
  23.  * LOOKAT checks if the message is of the requested type and comes from
  24.  * the right machine, returning 1 in case of affirmative answer 
  25.  */
  26.  
  27. #define LOOKAT(msg, mtype, mfrom, netp, froms) \
  28.     (((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \
  29.     (((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \
  30.     (((netp) == NULL) || \
  31.     (((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \
  32.     ? 1 : 0)
  33.  
  34. #define MORETIME(rtime, rtout) \
  35.     (((rtime).tv_sec > (rtout).tv_sec || \
  36.         ((rtime).tv_sec == (rtout).tv_sec && \
  37.         (rtime).tv_usec >= (rtout).tv_usec)) \
  38.     ? 0 : 1)
  39.  
  40. struct timeval rtime, rwait, rtout;
  41. struct tsp msgin;
  42. static struct tsplist {
  43.     struct tsp info;
  44.     struct sockaddr_in addr;
  45.     struct tsplist *p;
  46. } msgslist;
  47. struct sockaddr_in from;
  48. struct netinfo *fromnet;
  49.  
  50. /*
  51.  * `readmsg' returns message `type' sent by `machfrom' if it finds it 
  52.  * either in the receive queue, or in a linked list of previously received 
  53.  * messages that it maintains.
  54.  * Otherwise it waits to see if the appropriate message arrives within
  55.  * `intvl' seconds. If not, it returns NULL.
  56.  */
  57.  
  58. struct tsp *
  59. readmsg(type, machfrom, intvl, netfrom)
  60.  
  61. int type;
  62. char *machfrom;
  63. struct timeval *intvl;
  64. struct netinfo *netfrom;
  65. {
  66.     int length;
  67.     fd_set ready;
  68.     static struct tsplist *head = &msgslist;
  69.     static struct tsplist *tail = &msgslist;
  70.     struct tsplist *prev;
  71.     register struct netinfo *ntp;
  72.     register struct tsplist *ptr;
  73.  
  74.     if (trace) {
  75.         fprintf(fd, "looking for %s from %s\n",
  76.             tsptype[type], machfrom == NULL ? "ANY" : machfrom);
  77.         ptr = head->p;
  78.         fprintf(fd, "msgqueue:\n");
  79.         while (ptr != NULL) {
  80.             fprintf(fd, "\t");
  81.             print(&ptr->info, &ptr->addr);
  82.             ptr = ptr->p;
  83.         }
  84.     }
  85.  
  86.     ptr = head->p;
  87.     prev = head;
  88.  
  89.     /*
  90.      * Look for the requested message scanning through the 
  91.      * linked list. If found, return it and free the space 
  92.      */
  93.  
  94.     while (ptr != NULL) {
  95.         if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
  96.             msgin = ptr->info;
  97.             from = ptr->addr;
  98.             prev->p = ptr->p;
  99.             if (ptr == tail) 
  100.                 tail = prev;
  101.             free((char *)ptr);
  102.             fromnet = NULL;
  103.             if (netfrom == NULL)
  104.                 for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
  105.                     if ((ntp->mask & from.sin_addr.s_addr) ==
  106.                     ntp->net) {
  107.                         fromnet = ntp;
  108.                         break;
  109.                     }
  110.                 }
  111.             else
  112.                 fromnet = netfrom;
  113.             if (trace) {
  114.                 fprintf(fd, "readmsg: ");
  115.                 print(&msgin, &from);
  116.             }
  117.             return(&msgin);
  118.         } else {
  119.             prev = ptr;
  120.             ptr = ptr->p;
  121.         }
  122.     }
  123.  
  124.     /*
  125.      * If the message was not in the linked list, it may still be
  126.      * coming from the network. Set the timer and wait 
  127.      * on a select to read the next incoming message: if it is the
  128.      * right one, return it, otherwise insert it in the linked list.
  129.      */
  130.  
  131.     (void)gettimeofday(&rtime, (struct timezone *)0);
  132.     rtout.tv_sec = rtime.tv_sec + intvl->tv_sec;
  133.     rtout.tv_usec = rtime.tv_usec + intvl->tv_usec;
  134.     if (rtout.tv_usec > 1000000) {
  135.         rtout.tv_usec -= 1000000;
  136.         rtout.tv_sec++;
  137.     }
  138.  
  139.     FD_ZERO(&ready);
  140.     for (; MORETIME(rtime, rtout);
  141.         (void)gettimeofday(&rtime, (struct timezone *)0)) {
  142.         rwait.tv_sec = rtout.tv_sec - rtime.tv_sec;
  143.         rwait.tv_usec = rtout.tv_usec - rtime.tv_usec;
  144.         if (rwait.tv_usec < 0) {
  145.             rwait.tv_usec += 1000000;
  146.             rwait.tv_sec--;
  147.         }
  148.         if (rwait.tv_sec < 0) 
  149.             rwait.tv_sec = rwait.tv_usec = 0;
  150.  
  151.         if (trace) {
  152.             fprintf(fd, "readmsg: wait: (%d %d)\n", 
  153.                         rwait.tv_sec, rwait.tv_usec);
  154.         }
  155.         FD_SET(sock, &ready);
  156.         if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
  157.             &rwait)) {
  158.             length = sizeof(struct sockaddr_in);
  159.             if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 
  160.                         0, &from, &length) < 0) {
  161.                 syslog(LOG_ERR, "receiving datagram packet: %m");
  162.                 exit(1);
  163.             }
  164.  
  165.             bytehostorder(&msgin);
  166.  
  167.             if (msgin.tsp_vers > TSPVERSION) {
  168.                 if (trace) {
  169.                     fprintf(fd, "readmsg: version mismatch\n");
  170.                     /* should do a dump of the packet, but... */
  171.                 }
  172.                 continue;
  173.             }
  174.  
  175.             fromnet = NULL;
  176.             for (ntp = nettab; ntp != NULL; ntp = ntp->next)
  177.                 if ((ntp->mask & from.sin_addr.s_addr) ==
  178.                     ntp->net) {
  179.                     fromnet = ntp;
  180.                     break;
  181.                 }
  182.  
  183.             /*
  184.              * drop packets from nets we are ignoring permanently
  185.              */
  186.             if (fromnet == NULL) {
  187.                 /* 
  188.                  * The following messages may originate on
  189.                  * this host with an ignored network address
  190.                  */
  191.                 if (msgin.tsp_type != TSP_TRACEON &&
  192.                     msgin.tsp_type != TSP_SETDATE &&
  193.                     msgin.tsp_type != TSP_MSITE &&
  194. #ifdef    TESTING
  195.                     msgin.tsp_type != TSP_TEST &&
  196. #endif
  197.                     msgin.tsp_type != TSP_TRACEOFF) {
  198.                     if (trace) {
  199.                         fprintf(fd, "readmsg: discarded: ");
  200.                         print(&msgin, &from);
  201.                     }
  202.                     continue;
  203.                 }
  204.             }
  205.  
  206.             /*
  207.              * Throw away messages coming from this machine, unless
  208.              * they are of some particular type.
  209.              * This gets rid of broadcast messages and reduces
  210.              * master processing time.
  211.              */
  212.             if ( !(strcmp(msgin.tsp_name, hostname) != 0 ||
  213.                     msgin.tsp_type == TSP_SETDATE ||
  214. #ifdef TESTING
  215.                     msgin.tsp_type == TSP_TEST ||
  216. #endif
  217.                     msgin.tsp_type == TSP_MSITE ||
  218.                     (msgin.tsp_type == TSP_LOOP &&
  219.                     msgin.tsp_hopcnt != 10) ||
  220.                     msgin.tsp_type == TSP_TRACEON ||
  221.                     msgin.tsp_type == TSP_TRACEOFF)) {
  222.                 if (trace) {
  223.                     fprintf(fd, "readmsg: discarded: ");
  224.                     print(&msgin, &from);
  225.                 }
  226.                 continue;
  227.             }
  228.  
  229.             /*
  230.              * Send acknowledgements here; this is faster and avoids
  231.              * deadlocks that would occur if acks were sent from a 
  232.              * higher level routine.  Different acknowledgements are
  233.              * necessary, depending on status.
  234.              */
  235.             if (fromnet->status == MASTER)
  236.                 masterack();
  237.             else if (fromnet->status == SLAVE)
  238.                 slaveack();
  239.             else
  240.                 ignoreack();
  241.                 
  242.             if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
  243.                 if (trace) {
  244.                     fprintf(fd, "readmsg: ");
  245.                     print(&msgin, &from);
  246.                 }
  247.                 return(&msgin);
  248.             } else {
  249.                 tail->p = (struct tsplist *)
  250.                         malloc(sizeof(struct tsplist)); 
  251.                 tail = tail->p;
  252.                 tail->p = NULL;
  253.                 tail->info = msgin;
  254.                 tail->addr = from;
  255.             }
  256.         } else {
  257.             break;
  258.         }
  259.     }
  260.     return((struct tsp *)NULL);
  261. }
  262.  
  263. /*
  264.  * `slaveack' sends the necessary acknowledgements: 
  265.  * only the type ACK is to be sent by a slave 
  266.  */
  267.  
  268. slaveack()
  269. {
  270.     int length;
  271.     struct tsp resp;
  272.  
  273.     length = sizeof(struct sockaddr_in);
  274.     switch(msgin.tsp_type) {
  275.  
  276.     case TSP_ADJTIME:
  277.     case TSP_SETTIME:
  278.     case TSP_ACCEPT:
  279.     case TSP_REFUSE:
  280.     case TSP_TRACEON:
  281.     case TSP_TRACEOFF:
  282.     case TSP_QUIT:
  283.         resp = msgin;
  284.         resp.tsp_type = TSP_ACK;
  285.         resp.tsp_vers = TSPVERSION;
  286.         (void)strcpy(resp.tsp_name, hostname);
  287.         if (trace) {
  288.             fprintf(fd, "Slaveack: ");
  289.             print(&resp, &from);
  290.         }
  291.         bytenetorder(&resp);     /* this is not really necessary here */
  292.         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
  293.                         &from, length) < 0) {
  294.             syslog(LOG_ERR, "sendto: %m");
  295.             exit(1);
  296.         }
  297.         break;
  298.     default:
  299.         break;
  300.     }
  301. }
  302.  
  303. /*
  304.  * Certain packets may arrive from this machine on ignored networks.
  305.  * These packets should be acknowledged.
  306.  */
  307.  
  308. ignoreack()
  309. {
  310.     int length;
  311.     struct tsp resp;
  312.  
  313.     length = sizeof(struct sockaddr_in);
  314.     switch(msgin.tsp_type) {
  315.  
  316.     case TSP_TRACEON:
  317.     case TSP_TRACEOFF:
  318.         resp = msgin;
  319.         resp.tsp_type = TSP_ACK;
  320.         resp.tsp_vers = TSPVERSION;
  321.         (void)strcpy(resp.tsp_name, hostname);
  322.         if (trace) {
  323.             fprintf(fd, "Ignoreack: ");
  324.             print(&resp, &from);
  325.         }
  326.         bytenetorder(&resp);     /* this is not really necessary here */
  327.         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
  328.                         &from, length) < 0) {
  329.             syslog(LOG_ERR, "sendto: %m");
  330.             exit(1);
  331.         }
  332.         break;
  333.     default:
  334.         break;
  335.     }
  336. }
  337.  
  338. /*
  339.  * `masterack' sends the necessary acknowledgments 
  340.  * to the messages received by a master 
  341.  */
  342.  
  343. masterack()
  344. {
  345.     int length;
  346.     struct tsp resp;
  347.  
  348.     length = sizeof(struct sockaddr_in);
  349.  
  350.     resp = msgin;
  351.     resp.tsp_vers = TSPVERSION;
  352.     (void)strcpy(resp.tsp_name, hostname);
  353.  
  354.     switch(msgin.tsp_type) {
  355.  
  356.     case TSP_QUIT:
  357.     case TSP_TRACEON:
  358.     case TSP_TRACEOFF:
  359.     case TSP_MSITE:
  360.     case TSP_MSITEREQ:
  361.         resp.tsp_type = TSP_ACK;
  362.         bytenetorder(&resp);
  363.         if (trace) {
  364.             fprintf(fd, "Masterack: ");
  365.             print(&resp, &from);
  366.         }
  367.         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
  368.                         &from, length) < 0) {
  369.             syslog(LOG_ERR, "sendto: %m");
  370.             exit(1);
  371.         }
  372.         break;
  373.     case TSP_RESOLVE:
  374.     case TSP_MASTERREQ:
  375.         resp.tsp_type = TSP_MASTERACK;
  376.         bytenetorder(&resp);
  377.         if (trace) {
  378.             fprintf(fd, "Masterack: ");
  379.             print(&resp, &from);
  380.         }
  381.         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
  382.                         &from, length) < 0) {
  383.             syslog(LOG_ERR, "sendto: %m");
  384.             exit(1);
  385.         }
  386.         break;
  387.     case TSP_SETDATEREQ:
  388.         resp.tsp_type = TSP_DATEACK;
  389.         bytenetorder(&resp);
  390.         if (trace) {
  391.             fprintf(fd, "Masterack: ");
  392.             print(&resp, &from);
  393.         }
  394.         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
  395.                         &from, length) < 0) {
  396.             syslog(LOG_ERR, "sendto: %m");
  397.             exit(1);
  398.         }
  399.         break;
  400.     default:
  401.         break;
  402.     }
  403. }
  404.  
  405. /*
  406.  * Print a TSP message 
  407.  */
  408. print(msg, addr)
  409. struct tsp *msg;
  410. struct sockaddr_in *addr;
  411. {
  412.     switch (msg->tsp_type) {
  413.  
  414.     case TSP_LOOP:
  415.         fprintf(fd, "%s %d %d (#%d) %s %s\n",
  416.             tsptype[msg->tsp_type],
  417.             msg->tsp_vers,
  418.             msg->tsp_seq,
  419.             msg->tsp_hopcnt,
  420.             msg->tsp_name,
  421.             inet_ntoa(addr->sin_addr));
  422.         break;
  423.  
  424.     case TSP_SETTIME:
  425.     case TSP_ADJTIME:
  426.     case TSP_SETDATE:
  427.     case TSP_SETDATEREQ:
  428.         fprintf(fd, "%s %d %d (%d, %d) %s %s\n",
  429.             tsptype[msg->tsp_type],
  430.             msg->tsp_vers,
  431.             msg->tsp_seq,
  432.             msg->tsp_time.tv_sec, 
  433.             msg->tsp_time.tv_usec, 
  434.             msg->tsp_name,
  435.             inet_ntoa(addr->sin_addr));
  436.         break;
  437.  
  438.     default:
  439.         fprintf(fd, "%s %d %d %s %s\n",
  440.             tsptype[msg->tsp_type],
  441.             msg->tsp_vers,
  442.             msg->tsp_seq,
  443.             msg->tsp_name,
  444.             inet_ntoa(addr->sin_addr));
  445.         break;
  446.     }
  447. }
  448.